package com.ccp.dev.workflow.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ccp.dev.core.basic.base.BaseService;
import com.ccp.dev.core.basic.util.UUIDUtils;
import com.ccp.dev.core.basic.web.query.QueryFilter;
import com.ccp.dev.core.util.BeanUtils;
import com.ccp.dev.core.util.StringPool;
import com.ccp.dev.core.util.StringUtil;
import com.ccp.dev.system.dao.SysOrgDao;
import com.ccp.dev.system.dao.SysRoleDao;
import com.ccp.dev.system.dao.SysTypeKeyDao;
import com.ccp.dev.system.dao.UserPositionDao;
import com.ccp.dev.system.model.*;
import com.ccp.dev.system.service.SysOrgService;
import com.ccp.dev.workflow.dao.*;
import com.ccp.dev.workflow.model.*;
import com.ccp.dev.workflow.model.BpmDefAuthorizeType.BPMDEFAUTHORIZE_RIGHT_TYPE;
import com.ccp.dev.workflow.model.BpmDefAuthorizeUser.BPM_DEF_USER_RIGHT_TYPE;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhanghuichao zhhchyouxiang@126.com
 * @date 2019/7/9 13:43
 */
@Service
public class BpmDefAuthorizeService extends BaseService<BpmDefAuthorize> {

    @Resource
    private BpmDefAuthorizeDao bpmDefAuthorizeDao;
    @Resource
    private BpmDefAuthorizeTypeDao bpmDefAuthorizeTypeDao;
    @Resource
    private BpmDefAuthorizeUserDao bpmDefAuthorizeUserDao;
    @Resource
    private BpmDefAuthorizeActDao bpmDefAuthorizeActDao;
    @Resource
    private SysRoleDao sysRoleDao;
    @Resource
    private SysOrgDao sysOrgDao;
    @Resource
    private UserPositionDao userPositionDao;
    @Resource
    private ActDefModelDao actDefModelDao;
    @Resource
    private SysOrgService sysOrgService;
    @Resource
    private ActDefModelService actDefModelService;
    @Resource
    private SysTypeKeyDao sysTypeKeyDao;

    /**
     * 根据权限描述获取分管授权记录条数
     * @param queryFilter 过滤条件
     * @return 授权条数
     */
    public Integer getCountByDesc(QueryFilter queryFilter){
        return bpmDefAuthorizeDao.getCountByDesc(queryFilter);
    }

    /**
     * 新增或修改分管授权信息
     * @param authorize 分管授权对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void addOrUpdate(BpmDefAuthorize authorize){
        String authorizeId = authorize.getId();
        if(StringUtil.isEmpty(authorizeId)){
            authorizeId = UUIDUtils.getUUIDFor32();
            authorize.setId(authorizeId);
            bpmDefAuthorizeDao.add(authorize);
        }else{
            bpmDefAuthorizeDao.update(authorize);
            // 删除原来的从表信息，包括被授权用户子表及流程权限子表
            bpmDefAuthorizeTypeDao.delByAuthorizeId(authorizeId);
            bpmDefAuthorizeUserDao.delByAuthorizeId(authorizeId);
            bpmDefAuthorizeActDao.delByAuthorizeId(authorizeId);
        }
        // 保存分管授权类型表信息
        String authorizeTypes = authorize.getAuthorizeTypes();
        List<BpmDefAuthorizeType> bpmDefAuthorizeTypeList = toBpmDefAuthorizeTypeList(authorizeTypes, authorizeId);
        if(bpmDefAuthorizeTypeList.size() > 0){
            bpmDefAuthorizeTypeDao.addList(bpmDefAuthorizeTypeList);
        }
        // 保存流程分管授权用户子表信息
        String authorizeUsers = authorize.getOwnerNameJson();
        List<BpmDefAuthorizeUser> bpmDefAuthorizeUserList = toBpmDefAuthorizeUserList(authorizeUsers,authorizeId);
        if(bpmDefAuthorizeUserList.size() > 0){
            bpmDefAuthorizeUserDao.addList(bpmDefAuthorizeUserList);
        }
        // 保存流程分管授权流程子表信息
        String authorizeActs = authorize.getDefNameJson();
        List<BpmDefAuthorizeAct> bpmDefAuthorizeActList = toBpmDefAuthorizeActList(authorizeActs,authorizeId);
        if(bpmDefAuthorizeActList.size() > 0){
            bpmDefAuthorizeActDao.addList(bpmDefAuthorizeActList);
        }
    }

    /**
     * 根据id删除分管授权信息
     * @param id 授权id
     */
    @Transactional(rollbackFor = Exception.class)
    public void delAuthorizeById(String id){
        // 先级联删除授权类型、授权人员、授权流程
        bpmDefAuthorizeTypeDao.delByAuthorizeId(id);
        bpmDefAuthorizeUserDao.delByAuthorizeId(id);
        bpmDefAuthorizeActDao.delByAuthorizeId(id);
        bpmDefAuthorizeDao.delById(id);
    }

    /**
     * 批量删除分管授权信息
     * @param ids 授权id数组
     */
    @Transactional(rollbackFor = Exception.class)
    public void delAuthorizeByIdArray(String[] ids){
        // 先级联删除授权类型、授权人员、授权流程
        bpmDefAuthorizeTypeDao.delByAuthorizeIdArray(ids);
        bpmDefAuthorizeUserDao.delByAuthorizeIdArray(ids);
        bpmDefAuthorizeActDao.delByAuthorizeIdArray(ids);
        bpmDefAuthorizeDao.delByIdArray(ids);
    }

    /**
     * 授权类型转成授权类型列表
     * @param authorizeTypes 授权类型
     * @param authorizeId 授权id
     * @return 授权类型列表
     */
    private List<BpmDefAuthorizeType> toBpmDefAuthorizeTypeList(String authorizeTypes,String authorizeId){
        List<BpmDefAuthorizeType> bpmDefAuthorizeTypeList = new ArrayList<>();
        if(StringUtil.isNotEmpty(authorizeTypes) && StringUtil.isNotEmpty(authorizeId)){
            String [] types =  authorizeTypes.split(StringPool.COMMA);
            for(String authorizeType : types){
                if(StringUtil.isNotEmpty(authorizeType)){
                    BpmDefAuthorizeType bpmDefAuthorizeType = new BpmDefAuthorizeType();
                    bpmDefAuthorizeType.setId(UUIDUtils.getUUIDFor32());
                    bpmDefAuthorizeType.setAuthorizeId(authorizeId);
                    bpmDefAuthorizeType.setAuthorizeType(authorizeType);
                    bpmDefAuthorizeTypeList.add(bpmDefAuthorizeType);
                }
            }
        }
        return bpmDefAuthorizeTypeList;
    }

    /**
     * 授权人员转成授权人员列表
     * @param authorizeUsers 授权人员
     * @param authorizeId 授权id
     * @return 授权人员列表
     */
    private List<BpmDefAuthorizeUser> toBpmDefAuthorizeUserList(String authorizeUsers,String authorizeId){
        List<BpmDefAuthorizeUser> bpmDefAuthorizeUserList = new ArrayList<>();
        if(StringUtil.isEmpty(authorizeUsers) || StringUtil.isEmpty(authorizeId)){
            return bpmDefAuthorizeUserList;
        }
        JSONArray userListArray = JSONArray.parseArray(authorizeUsers);
        userListArray.forEach(tempUser -> {
            JSONObject user  = (JSONObject)tempUser;
            JSONArray ownerList = user.getJSONArray("ownerList");
            ownerList.forEach(tempOwner -> {
                JSONObject owner = (JSONObject)tempOwner;
                BpmDefAuthorizeUser bpmDefAuthorizeUser = new BpmDefAuthorizeUser();
                bpmDefAuthorizeUser.setId(UUIDUtils.getUUIDFor32());
                bpmDefAuthorizeUser.setAuthorizeId(authorizeId);
                bpmDefAuthorizeUser.setOwnerId(owner.getString("ownerId"));
                bpmDefAuthorizeUser.setOwnerName(owner.getString("ownerName"));
                bpmDefAuthorizeUser.setRightType(user.getString("rightType"));
                bpmDefAuthorizeUserList.add(bpmDefAuthorizeUser);
            });
        });
        return bpmDefAuthorizeUserList;
    }

    /**
     * 授权流程转成授权流程列表
     * @param authorizeActs 授权流程
     * @param authorizeId 授权id
     * @return 授权流程列表
     */
    private List<BpmDefAuthorizeAct> toBpmDefAuthorizeActList(String authorizeActs,String authorizeId){
        List<BpmDefAuthorizeAct> bpmDefAuthorizeActList = new ArrayList<>();
        if(StringUtil.isEmpty(authorizeActs) || StringUtil.isEmpty(authorizeId)){
            return bpmDefAuthorizeActList;
        }
        JSONArray authorizeActList = JSONArray.parseArray(authorizeActs);
        authorizeActList.forEach(tempAct -> {
            JSONObject act = (JSONObject)tempAct;
            BpmDefAuthorizeAct bpmDefAuthorizeAct = new BpmDefAuthorizeAct();
            bpmDefAuthorizeAct.setId(UUIDUtils.getUUIDFor32());
            bpmDefAuthorizeAct.setAuthorizeId(authorizeId);
            bpmDefAuthorizeAct.setDefKey(act.getString("defKey"));
            bpmDefAuthorizeAct.setDefName(act.getString("defName"));
            bpmDefAuthorizeAct.setRightContent(act.getJSONObject("rightContent").toJSONString());
            bpmDefAuthorizeActList.add(bpmDefAuthorizeAct);
        });
        return bpmDefAuthorizeActList;
    }

    /**
     * 查询自己相关的分管授权的流程权限
     * @param userId  用户id
     * @param authorizeType 权限类型
     * @param isRight 是否包括流程的权限
     * @param isMyDef 是否包括自己创建的流程的所有权限
     */
    public Map<String, Object> getActRightsByUserMap(String userId, String authorizeType, boolean isRight, boolean isMyDef) {
        Map<String, Object> rightMap = new HashMap<>(16);
        Map<String, Object> map = new HashMap<>(16);
        map.put("authorizeType", authorizeType);
        StringBuilder authorizeIds = new StringBuilder();

        map.put("all", BPM_DEF_USER_RIGHT_TYPE.ALL);
        map.put("user", BPM_DEF_USER_RIGHT_TYPE.USER);
        map.put("role", BPM_DEF_USER_RIGHT_TYPE.ROLE);
        map.put("publicRole", BPM_DEF_USER_RIGHT_TYPE.PUBLICROLE);
        map.put("org", BPM_DEF_USER_RIGHT_TYPE.ORG);
        map.put("position", BPM_DEF_USER_RIGHT_TYPE.POSITION);
        map.put("grant", BPM_DEF_USER_RIGHT_TYPE.GRANT);

        // 直接分配到自己id
        map.put("userId", userId);

        // 用户角色查询
        List<SysRole> roles = sysRoleDao.queryByUserId(userId);
        List<String> roleIdList = new ArrayList<>();
        if (BeanUtils.isNotEmpty(roles)) {
            for (SysRole sysRole : roles) {
                roleIdList.add(sysRole.getRoleId());
            }
        }

        //用户组织查询
        SysOrg sysOrg = sysOrgDao.getOrgByUserId(userId);
        Map<String, String> mapPath = new HashMap<>(16);
        if (BeanUtils.isNotEmpty(sysOrg)) {
            String orgIds = "'" + sysOrg.getOrgId() + "'";
            StringBuilder grantIds = new StringBuilder();
            // 查询自己上级部分的信息
            String paths = sysOrg.getPath();
            if (StringUtil.isNotEmpty(paths)) {
                String[] pathArray = paths.split("\\.");
                for (String path : pathArray) {
                    if (!mapPath.containsKey(path)) {
                        mapPath.put(path, path);
                        grantIds.append("'").append(path).append("',");
                    }
                }
            }

            map.put("orgIds", orgIds);
            if (grantIds.length() > 0) {
                grantIds = new StringBuilder(grantIds.substring(0, grantIds.length() - 1));
                map.put("grantIds", grantIds.toString());
            }

        }

        // 处理角色的内容
        if (BeanUtils.isNotEmpty(roleIdList)) {
            StringBuilder roleIds = new StringBuilder();
            for (String roleId : roleIdList) {
                roleIds.append("'").append(roleId).append("',");
            }
            roleIds = new StringBuilder(roleIds.substring(0, roleIds.length() - 1));
            map.put("roleIds", roleIds.toString());
        }

        // 用户岗位查询
        List<UserPosition> userPositions = userPositionDao.queryByUserId(userId);
        if (BeanUtils.isNotEmpty(userPositions)) {
            StringBuilder positionIds = new StringBuilder();
            for (UserPosition userPosition : userPositions) {
                positionIds.append("'").append(userPosition.getPosId()).append("',");
            }
            positionIds = new StringBuilder(positionIds.substring(0, positionIds.length() - 1));
            map.put("positionIds", positionIds.toString());
        }

        // 转换流程授权的内容
        Map<String, AuthorizeRight> authorizeRightMap = new HashMap<>(16);
        Map<String, AuthorizeRight> myRightMap= new HashMap<>(16);

        // 查询自己创建的流程Key(拥有所有权)
        if (isMyDef) {
            List<String> myModelList = actDefModelDao.queryModelKeyByCreateBy(userId);
            if (!myModelList.isEmpty()) {
                // 如果需要所有权限就直接虚拟一个有处理权限的对象
                if (isRight) {
                    for (String modelKey : myModelList) {
                        AuthorizeRight authorizeRight = new AuthorizeRight();
                        authorizeRight.setRightByAuthorizeType("Y", BPMDEFAUTHORIZE_RIGHT_TYPE.MANAGEMENT);
                        authorizeRightMap.put(modelKey, authorizeRight);
                        myRightMap.put(modelKey, authorizeRight);
                        authorizeIds.append("'").append(modelKey).append("',");
                    }
                } else {
                    // 不需要权限时
                    for (String modelKey : myModelList) {
                        authorizeIds.append("'").append(modelKey).append("',");
                    }
                }

            }
        }

        // 获取流程授权的列表内容
        List<BpmDefAuthorizeAct> actRightList = bpmDefAuthorizeActDao.queryActRightByUserMap(map);
        if (!actRightList.isEmpty()) {
            if (isRight) {
                for (BpmDefAuthorizeAct authorizeAct : actRightList) {
                    String defKey = authorizeAct.getDefKey();
                    // 是属于自己创建的流程是有所有权的，不用解析
                    if (myRightMap.get(defKey) != null) {
                        continue;
                    }
                    String rightContent = authorizeAct.getRightContent();
                    AuthorizeRight authorizeRight = authorizeRightMap.get(defKey);
                    if (authorizeRight != null) {
                        authorizeRight.setRightByNeed("Y",rightContent,authorizeType);
                    }else {
                        authorizeIds.append("'").append(defKey).append("',");
                        authorizeRight = new AuthorizeRight();
                        authorizeRight.setAuthorizeType(authorizeType);
                        authorizeRight.setDefKey(defKey);
                        authorizeRight.setRightContent(rightContent);
                    }
                    authorizeRightMap.put(defKey, authorizeRight);
                }
            }else {
                for (BpmDefAuthorizeAct authorizeAct : actRightList) {
                    authorizeIds.append("'").append(authorizeAct.getDefKey()).append("',");
                }
            }

        }
        if (StringUtil.isNotEmpty(authorizeIds.toString())) {
            authorizeIds = new StringBuilder(authorizeIds.substring(0, authorizeIds.length() - 1));
        }

        rightMap.put("authorizeIds", authorizeIds.toString());
        rightMap.put("authorizeRightMap", authorizeRightMap);
        return rightMap;
    }

    /**
     * 根据流程列表反查流程分类列表
     * @param queryFilter 过滤条件
     * @return 分类列表
     */
    public List<GlobalType> getFlowTypeByFlow(QueryFilter queryFilter){
        String catKey = queryFilter.get("catKey").toString();
        boolean hasRoot = queryFilter.get("hasRoot") != null && Boolean.parseBoolean(queryFilter.get("hasRoot").toString());
        List<ActDefModel> authorizedModelList = actDefModelService.queryAuthorizedList(queryFilter);
        List<String> modelKeys = authorizedModelList.stream().map(ActDefModel::getModelKey).collect(Collectors.toList());
        List<GlobalType> flowTypeList = bpmDefAuthorizeDao.getFlowTypeByFlow(modelKeys);
        if (hasRoot){
            SysTypeKey sysTypeKey = sysTypeKeyDao.getSysTypeKeyByKey(catKey);
            GlobalType globalType = new GlobalType();
            globalType.setTypeName(sysTypeKey.getTypeName());
            globalType.setCatKey(sysTypeKey.getTypeKey());
            globalType.setIsParent("true");
            globalType.setParentId("0");
            globalType.setTypeId(sysTypeKey.getTypeId());
            globalType.setType(sysTypeKey.getType());
            globalType.setNodePath(sysTypeKey.getTypeId() + ".");
            flowTypeList.add(0, globalType);
        }
        return flowTypeList;
    }
}
